﻿using DimensionsHelper.Serialization.Enumerator;

namespace DimensionsHelper.LanguageService.Syntax;

[EnumConverter]
[EnumStringConvertable(typeof(SyntaxKinds), IgnoreCase = true, AttributeConstructorArgIndex = 0,
    AttributeType = typeof(TokenAttribute), TargetName = "Token", AttributeDerivedType = true)]
[EnumStringConvertable(typeof(SyntaxKinds), IgnoreCase = true, AttributeConstructorArgIndex = 0,
    AttributeType = typeof(KeywordAttribute), TargetName = "Keyword", AttributeDerivedType = true,
    ConditionType = typeof(KeywordContexts), ConditionConstructorArgIndex = 1)]
[EnumStringConvertable(typeof(SyntaxKinds), IgnoreCase = true, AttributeConstructorArgIndex = 0,
    AttributeType = typeof(ModifierAttribute), TargetName = "Modifier", AttributeDerivedType = false,
    ConditionType = typeof(KeywordContexts), ConditionConstructorArgIndex = 1)]
[EnumAttributePropertySelector(typeof(SyntaxKinds), typeof(OperatorAttribute),
    ConditionType = typeof(OperatorContexts), ConditionArgumentName = nameof(OperatorAttribute.Context),
    ArgumentName = nameof(OperatorAttribute.Priority))]
[EnumAttributePropertySelector(typeof(SyntaxKinds), typeof(OperatorAttribute),
    ConditionType = typeof(OperatorContexts), ConditionArgumentName = nameof(OperatorAttribute.Context),
    ArgumentName = nameof(OperatorAttribute.Kind))]
public static partial class SyntaxFacts
{
    /// <summary>
    ///     如果指定语法类型是Token，返回<see langword="true" />
    /// </summary>
    public static bool IsToken(SyntaxKinds kind)
    {
        return TryConvertTokenToString(kind, out _);
    }


    /// <summary>
    ///     如果语法类型是关键字，返回<see langword="true" />
    /// </summary>
    public static bool IsKeyword(SyntaxKinds kind)
    {
        return TryConvertKeywordToString(kind, KeywordContexts.All, out _);
    }


    /// <summary>
    ///     如果语法类型是指定上下文类型下的关键字，返回<see langword="true" />
    /// </summary>
    public static bool IsKeyword(SyntaxKinds kind, KeywordContexts context)
    {
        return TryConvertKeywordToString(kind, context, out _);
    }


    /// <summary>
    ///     判断给定类型的Token是否是操作符。
    /// </summary>
    public static bool IsOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return TryConvertSyntaxKindsToOperatorKind(kind, context, out _);
    }


    /// <summary>
    ///     判断给定类型的Token在给定上下文类型下是否是指定类型的操作符
    /// </summary>
    private static bool IsOperator(SyntaxKinds kind, OperatorContexts context, OperatorKind operatorKind)
    {
        return TryConvertSyntaxKindsToOperatorKind(kind, context, out OperatorKind opKind)
               && (opKind & operatorKind) != 0;
    }


    /// <summary>
    ///     判断给定类型的Token是否是一元操作符。
    /// </summary>
    public static bool IsUnaryOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return IsOperator(kind, context, OperatorKind.Unary);
    }


    /// <summary>
    ///     <inheritdoc cref="IsUnaryOperator(SyntaxKinds, OperatorContexts)" />
    /// </summary>
    public static bool IsUnaryOperatorUnchecked(SyntaxKinds kind)
    {
        return IsUnaryOperator(kind, OperatorContexts.All);
    }


    /// <summary>
    ///     判断给定类型的Token是否是二元操作符。
    /// </summary>
    public static bool IsBinaryOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return IsOperator(kind, context, OperatorKind.Binary);
    }


    /// <summary>
    ///     <inheritdoc cref="IsBinaryOperator" />
    /// </summary>
    public static bool IsBinaryOperatorUnchecked(SyntaxKinds kind)
    {
        return IsBinaryOperator(kind, OperatorContexts.All);
    }


    /// <summary>
    ///     判断给定类型的Token是否是比较类型的二元操作符
    /// </summary>
    public static bool IsCompareOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return IsOperator(kind, context, OperatorKind.Compare);
    }


    /// <inheritdoc cref="IsCompareOperator(SyntaxKinds, OperatorContexts)" />
    public static bool IsCompareOperatorUnchecked(SyntaxKinds kind)
    {
        return IsCompareOperator(kind, OperatorContexts.All);
    }


    /// <summary>
    ///     判断给定类型的Token是否是数值计算类型的操作符
    /// </summary>
    public static bool IsComputeOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return IsOperator(kind, context, OperatorKind.Compute);
    }


    /// <inheritdoc cref="IsComputeOperator(SyntaxKinds, OperatorContexts)" />
    public static bool IsComputeOperatorUnchecked(SyntaxKinds kind)
    {
        return IsComputeOperator(kind, OperatorContexts.All);
    }


    /// <summary>
    ///     判断给定类型的Token是否是逻辑类型的操作符
    /// </summary>
    public static bool IsLogicalOperator(SyntaxKinds kind, OperatorContexts context)
    {
        return IsOperator(kind, context, OperatorKind.Logical);
    }


    /// <inheritdoc cref="IsLogicalOperator(SyntaxKinds, OperatorContexts)" />
    public static bool IsLogicalOperatorUnchecked(SyntaxKinds kind)
    {
        return IsLogicalOperator(kind, OperatorContexts.All);
    }


    /// <summary>
    ///     如果指定语法类型是修饰符，返回<see langword="true" />
    /// </summary>
    public static bool IsModifier(SyntaxKinds kind)
    {
        return TryConvertModifierToString(kind, KeywordContexts.Declaration, out _);
    }


    /// <summary>
    ///     如果给定语法类型是常量类型，返回<see langword="true" />。
    /// </summary>
    /// <param name="kind">语法类型</param>
    public static bool IsLiteralKind(SyntaxKinds kind)
    {
        return kind is SyntaxKinds.String or SyntaxKinds.Integer or SyntaxKinds.Double or SyntaxKinds.Boolean
            or SyntaxKinds.Categorical or SyntaxKinds.Null;
    }
}